﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Graphics;
using GameEngine.Camera;
using GameEngine.EntityComponents;
using GameEngine.Managers.IManagers;
using GameEngine.Entities;
using PvT.EntityComponent;

namespace PvT.Entities
{
    public class PlayerEntity : AbstractDrawableEntity
    {
        #region Fields

        private int singleImageWidth = 40;
        private int singleImageHeight = 40;

        // several images
        private int imageFramesRun = 4;

        // single image animations
        private int standImage = 0;
        private int jumpImage = 1;
        private int fallImage = 2;
        private int deadFrame = 3;

        private int animationFrameRate = 12;

        private bool plasmaImmune = false;

        private Color playerColor = Color.White;

        #endregion
        #region Properties

        /// <summary>
        /// Gets or sets a value indicating whether [plasma immune].
        /// </summary>
        /// <value>
        ///   <c>true</c> if [plasma immune]; otherwise, <c>false</c>.
        /// </value>
        public bool PlasmaImmune
        {
            get { return plasmaImmune; }
            set
            {
                plasmaImmune = value;
                if (plasmaImmune)
                    this.texture = game.Content.Load<Texture2D>("Player/prince-green");
                else
                    this.texture = game.Content.Load<Texture2D>("Player/prince");
            }
        }

        public override Rectangle BoundingRectangle
        {
            get { return new Rectangle((int)position.X, (int)position.Y, (int)(singleImageWidth * scale), (int)(singleImageHeight * scale)); }
            set { base.BoundingRectangle = value; }
        }

        #endregion

        /// <summary>
        /// Initializes a new instance of the <see cref="PlayerEntity" /> class.
        /// </summary>
        /// <param name="components">The components.</param>
        /// <param name="isActive">if set to <c>true</c> [is active].</param>
        /// <param name="isVisible">if set to <c>true</c> [is visible].</param>
        /// <param name="position">The position.</param>
        /// <param name="game">The game.</param>
        public PlayerEntity(List<IEntityComponent> components, bool isActive, bool isVisible, Vector2 position, Game game) :
            base(components, isActive, isVisible, position, game)
        {
            this.scale = 0.6f;
            if (isActive == true)
            {
                components.Add(new MoveableComponent(this, 0.1f, false));
                components.Add(new CollidableComponent(this, 0.1f));
                components.Add(new TerminateableComponent(this));
                PlayerSoundComponent psc = new PlayerSoundComponent(this);
                psc.JumpSound = "Sound/jumpSound";
                psc.CollisionSoundPowerUp = "Sound/powerUp";
                components.Add(psc);
            }
        }

        /// <summary>
        /// Loads the content.
        /// </summary>
        public override void LoadContent()
        {
            base.texture = game.Content.Load<Texture2D>("Player/prince");
        }

        /// <summary>
        /// Updates the playerEntity
        /// </summary>
        /// <param name="gameTime">The game time.</param>
        public override void Update(GameTime gameTime)
        {
            // Game Over
            if (!(((TerminateableComponent)this.GetComponent(typeof(TerminateableComponent))).IsAlive()))
                return;

            ((Camera2D)game.Services.GetService(typeof(Camera2D))).Pos = this.position;
            base.Update(gameTime);
        }

        public override void Draw(SpriteBatch spriteBatch, GameTime gameTime)
        {
            CollidableComponent collide = (CollidableComponent)this.GetComponent(typeof(CollidableComponent));

            if (this.GetComponent(typeof(MoveableComponent)) != null)
            {
                MoveableComponent moveable = (MoveableComponent)this.GetComponent(typeof(MoveableComponent));

                int runFrame = (int)(gameTime.TotalGameTime.TotalSeconds * animationFrameRate) % imageFramesRun;

                if (moveable.movementDirection == MoveableComponent.MoveDir.Forward && moveable.xVelocity != 0)
                {
                    // animate go right
                    sourceRectangle = new Rectangle((runFrame * singleImageWidth), singleImageHeight, singleImageWidth, singleImageHeight);
                    effects = SpriteEffects.None;
                }
                else if (moveable.movementDirection == MoveableComponent.MoveDir.Backward && moveable.xVelocity != 0)
                {
                    // animate go left
                    sourceRectangle = new Rectangle((runFrame * singleImageWidth), singleImageHeight, singleImageWidth, singleImageHeight);
                    effects = SpriteEffects.FlipHorizontally;
                }
                else
                {
                    // animate standing still
                    sourceRectangle = new Rectangle(standImage, 0, singleImageWidth, singleImageHeight);
                }

                
                if (moveable.movementState == MoveableComponent.State.InAir && moveable.yVelocity < 0)
                {
                    // animate falling
                    sourceRectangle = new Rectangle((jumpImage * singleImageWidth), 0, singleImageWidth, singleImageHeight);
                }
                else if (moveable.movementState == MoveableComponent.State.InAir && moveable.yVelocity > 0)
                {
                    // animate jumping
                    sourceRectangle = new Rectangle((fallImage * singleImageWidth), 0, singleImageWidth, singleImageHeight);
                }


                if (moveable.movementState == MoveableComponent.State.Dead)
                {
                    // animate dead
                    sourceRectangle = new Rectangle((deadFrame * singleImageWidth), singleImageHeight*2, singleImageWidth, singleImageHeight);
                }
            }


            base.Draw(spriteBatch, gameTime);
        }

        /// <summary>
        /// Sets the scale.
        /// </summary>
        /// <param name="scale">The scale.</param>
        public void SetScale(float scale)
        {
            this.scale = scale;
        }
    }
}
